package cc.wanforme.chipmunity.security.handlers;

import java.io.IOException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

import cc.wanforme.chipmunity.common.CookieUtil;
import cc.wanforme.chipmunity.common.IpUtils;
import cc.wanforme.chipmunity.security.Excepetion.InvalidTokenException;
import cc.wanforme.chipmunity.security.service.PersistentLoginService;
import cc.wanforme.chipmunity.system.po.user.LoginLog;
import cc.wanforme.chipmunity.system.po.user.PersistentLogin;
import cc.wanforme.chipmunity.system.service.interfaces.LoginLogService;

/**
 * 需要在登录过滤器中检查 记住我的参数（例如：remember-me，以登录过滤器为准）
 * @author wanne
 * 2019年8月13日
 * 
 */
public class CustomTokenFilter implements Filter{
	private static final Logger log = LoggerFactory.getLogger(CustomTokenFilter.class);
	
	/** token的cookie名*/
	public static final String TOKEN_NAME="cmcode";
	
	private final UserDetailsService userDetailsService;
	private final LoginLogService loginLogService;
	private final PersistentLoginService persistentLoginService;
	
	public CustomTokenFilter(UserDetailsService userDetailsService, LoginLogService loginLogService,
				PersistentLoginService persistentLoginService) {
		super();
		this.userDetailsService = userDetailsService;
		this.loginLogService = loginLogService;
		this.persistentLoginService = persistentLoginService;
	}
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		if(request.getServletPath().equals("/login")) { // 排除登录
			chain.doFilter(req, res);
			return;
		}
		
		String cmcode = CookieUtil.getCookieValue(request, TOKEN_NAME);
		
		if(!StringUtils.isEmpty(cmcode)) {
			String username = null;
			try {
				username = verify(cmcode);
				if(username !=null ) {
					verifySuccess(username, request);
					// 设置token为httpOnly，不允许js读取
					//((HttpServletResponse)res).addHeader("Set-Cookie", "uid=112; Path=/; HttpOnly");
					/*
					String contextPath = request.getServletContext().getContextPath();
					((HttpServletResponse)res).addHeader("Set-Cookie", TOKEN_NAME + "=" + cmcode + "; Path=" + contextPath + "; HttpOnly");
					*/
				}else {
					verifyFail();
				}
			} catch (InvalidTokenException e) {
				log.info("token验证失败");
				log.error(e.getMessage());
			}
		}
		
		chain.doFilter(req, res);
	}
	
	@Override
	public void destroy() {
		
	}

	/**验证
	 * @return 返回username
	 * @throws InvalidTokenException 
	 */
	protected String verify(String token) throws InvalidTokenException {
		// 简单的与数据库比对
		PersistentLogin persistentLogin = persistentLoginService.verifyToken(token);
		
		// 其它验证 （过期验证等...）
		// TO DO ...
		// 最重要的是如何验证token不是伪造其它的
		if(persistentLogin == null) {
			throw new InvalidTokenException("无效的token");
		}
		if(persistentLogin.getExpire().before(new Date())) {
			throw new InvalidTokenException("token已过期");
		}
		
		return persistentLogin==null ? null:persistentLogin.getUsername();
	}
	
	/**
	 * 验证通过
	 */
	protected void verifySuccess(String username, HttpServletRequest request) {
		// 如果是第一次进入过滤器，说明还没有登录，那么就自动登陆
		if(SecurityContextHolder.getContext().getAuthentication() == null) {
			// 设置登录信息
			UserDetails userDetails = userDetailsService.loadUserByUsername(username);
			if(userDetails == null)
				return;
			
			// 和CustomJSONLoginFilter中保持一致
			UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(
					username, userDetails.getPassword(), userDetails.getAuthorities());
			SecurityContextHolder.getContext().setAuthentication(upat);
		}
		
		Cookie cookie = CookieUtil.getCookie(request, TOKEN_NAME);
		cookie.setHttpOnly(true);
		// 添加登录记录
		LoginLog loginLog = new LoginLog(username, IpUtils.getAddress(request), IpUtils.getIpAddr(request), new Date());
		loginLogService.saveLoginLog(loginLog);
	}
	
	/**
	 * 验证失败
	 */
	protected void verifyFail() {
		
	}
	
	
	
}
